using System;

namespace GameFrame
{
    public class AssertException : Exception
    {
        public AssertException()
        {
        }

        public AssertException(string msg)
            : base(msg)
        {
        }
    }
    public static class Assert
    {
        public static void Fail() => throw new AssertException();
        
        public static void Fail(string msg) => throw new AssertException(msg);
        
        public static void Fail(string format, params object[] args) => throw new AssertException(string.Format(format, args));
        
        public static void Always(object condition)
        {
            if (condition == null)
                throw new AssertException();
        }
        
        public static unsafe void Always(void* condition)
        {
            if ((IntPtr) condition == IntPtr.Zero)
                throw new AssertException();
        }

        /// <summary>
        /// Throws an <see cref="T:Quantum.AssertException" /> if condition is false.
        /// Will not be stripped in release configuration.
        /// </summary>
        /// <param name="condition">Condition</param>
        public static void Always([DoesNotReturnIf(false)] bool condition)
        {
            if (!condition)
                throw new AssertException();
        }

        /// <summary>
        /// Throws an <see cref="T:Quantum.AssertException" /> if condition is false.
        /// Will not be stripped in release configuration.
        /// </summary>
        /// <param name="condition">Condition</param>
        /// <param name="message">Exception message</param>
        public static void Always([DoesNotReturnIf(false)] bool condition, string message)
        {
            if (!condition)
                throw new AssertException(message);
        }

        /// <summary>
        /// Throws an <see cref="T:Quantum.AssertException" /> if condition is false.
        /// Will not be stripped in release configuration.
        /// </summary>
        /// <param name="condition">Condition</param>
        /// <param name="arg0">Argument is added to the exception message using arg0.ToString()</param>
        public static void Always<T0>([DoesNotReturnIf(false)] bool condition, T0 arg0)
        {
            if (!condition)
                throw new AssertException(string.Format("arg0:{0}", (object) arg0));
        }

        /// <summary>
        /// Throws an <see cref="T:Quantum.AssertException" /> if condition is false.
        /// Will not be stripped in release configuration.
        /// </summary>
        /// <param name="condition">Condition</param>
        /// <param name="arg0">Argument is added to the exception message using arg0.ToString()</param>
        /// <param name="arg1">Argument is added to the exception message using arg1.ToString()</param>
        public static void Always<T0, T1>([DoesNotReturnIf(false)] bool condition, T0 arg0, T1 arg1)
        {
            if (!condition)
                throw new AssertException(string.Format("arg0:{0} arg1:{1}", (object) arg0, (object) arg1));
        }

        /// <summary>
        /// Throws an <see cref="T:Quantum.AssertException" /> if condition is false.
        /// Will not be stripped in release configuration.
        /// </summary>
        /// <param name="condition">Condition</param>
        /// <param name="arg0">Argument is added to the exception message using arg0.ToString()</param>
        /// <param name="arg1">Argument is added to the exception message using arg1.ToString()</param>
        /// <param name="arg2">Argument is added to the exception message using arg2.ToString()</param>
        public static void Always<T0, T1, T2>([DoesNotReturnIf(false)] bool condition, T0 arg0, T1 arg1, T2 arg2)
        {
            if (!condition)
                throw new AssertException(string.Format("arg0:{0} arg1:{1} arg2:{2}", (object) arg0, (object) arg1, (object) arg2));
        }

        /// <summary>
        /// Throws an <see cref="T:Quantum.AssertException" /> if condition is false.
        /// Will not be stripped in release configuration.
        /// </summary>
        /// <param name="condition">Condition</param>
        /// <param name="arg0">Argument is added to the exception message using arg0.ToString()</param>
        /// <param name="arg1">Argument is added to the exception message using arg1.ToString()</param>
        /// <param name="arg2">Argument is added to the exception message using arg2.ToString()</param>
        /// <param name="arg3">Argument is added to the exception message using arg3.ToString()</param>
        public static void Always<T0, T1, T2, T3>([DoesNotReturnIf(false)] bool condition, T0 arg0, T1 arg1, T2 arg2, T3 arg3)
        {
            if (!condition)
                throw new AssertException(string.Format("arg0:{0} arg1:{1} arg2:{2} arg3:{3}", (object) arg0, (object) arg1, (object) arg2, (object) arg3));
        }

        /// <summary>
        /// Throws an <see cref="T:Quantum.AssertException" /> if condition is false.
        /// Will not be stripped in release configuration.
        /// </summary>
        /// <param name="condition">Condition</param>
        /// <param name="format">Exception message</param>
        /// <param name="arg0">Argument is added to the exception message using arg0.ToString()</param>
        public static void Always<T0>([DoesNotReturnIf(false)] bool condition, string format, T0 arg0)
        {
            if (!condition)
                throw new AssertException(string.Format(format, (object) arg0));
        }

        /// <summary>
        /// Throws an <see cref="T:Quantum.AssertException" /> if condition is false.
        /// Will not be stripped in release configuration.
        /// </summary>
        /// <param name="condition">Condition</param>
        /// <param name="format">Exception message</param>
        /// <param name="arg0">Argument is added to the exception message using string.Format()</param>
        /// <param name="arg1">Argument is added to the exception message using string.Format()</param>
        public static void Always<T0, T1>([DoesNotReturnIf(false)] bool condition, string format, T0 arg0, T1 arg1)
        {
            if (!condition)
                throw new AssertException(string.Format(format, (object) arg0, (object) arg1));
        }

        /// <summary>
        /// Throws an <see cref="T:Quantum.AssertException" /> if condition is false.
        /// Will not be stripped in release configuration.
        /// </summary>
        /// <param name="condition">Condition</param>
        /// <param name="format">Exception message</param>
        /// <param name="arg0">Argument is added to the exception message using string.Format()</param>
        /// <param name="arg1">Argument is added to the exception message using string.Format()</param>
        /// <param name="arg2">Argument is added to the exception message using string.Format()</param>
        public static void Always<T0, T1, T2>(
            [DoesNotReturnIf(false)] bool condition,
            string format,
            T0 arg0,
            T1 arg1,
            T2 arg2)
        {
            if (!condition)
                throw new AssertException(string.Format(format, (object) arg0, (object) arg1, (object) arg2));
        }

        /// <summary>
        /// Throws an <see cref="T:Quantum.AssertException" /> if condition is false.
        /// Will not be stripped in release configuration.
        /// </summary>
        /// <param name="condition">Condition</param>
        /// <param name="format">Exception message</param>
        /// <param name="args">Argument list added to the message using string.Format()</param>
        public static void Always([DoesNotReturnIf(false)] bool condition, string format, params object[] args)
        {
            if (!condition)
                throw new AssertException(string.Format(format, args));
        }

        /// <summary>
        /// Throws an <see cref="T:Quantum.AssertException" /> if condition is null.
        /// Is stripped in release configuration.
        /// </summary>
        /// <param name="condition">Condition object</param>
        [Conditional("DEBUG")]
        public static void Check(object condition)
        {
            if (condition == null)
                throw new AssertException();
        }

        /// <summary>
        /// Throws an <see cref="T:Quantum.AssertException" /> if condition is null.
        /// Is stripped in release configuration.
        /// </summary>
        /// <param name="condition">Condition pointer</param>
        [Conditional("DEBUG")]
        public static unsafe void Check(void* condition)
        {
            if ((IntPtr) condition == IntPtr.Zero)
                throw new AssertException();
        }

        /// <summary>
        /// Throws an <see cref="T:Quantum.AssertException" /> if condition is false.
        /// Is stripped in release configuration.
        /// </summary>
        /// <param name="condition">Condition</param>
        [Conditional("DEBUG")]
        public static void Check([DoesNotReturnIf(false)] bool condition)
        {
            if (!condition)
                throw new AssertException();
        }

        /// <summary>
        /// Throws an <see cref="T:Quantum.AssertException" /> if condition is false.
        /// Is stripped in release configuration.
        /// </summary>
        /// <param name="condition">Condition</param>
        /// <param name="error">Exception message</param>
        [Conditional("DEBUG")]
        public static void Check([DoesNotReturnIf(false)] bool condition, string error)
        {
            if (!condition)
                throw new AssertException(error);
        }

        /// <summary>
        /// Throws an <see cref="T:Quantum.AssertException" /> if condition is false.
        /// Is stripped in release configuration.
        /// </summary>
        /// <param name="condition">Condition</param>
        /// <param name="arg0">Argument is added to the exception message using arg0.ToString()</param>
        [Conditional("DEBUG")]
        public static void Check<T0>([DoesNotReturnIf(false)] bool condition, T0 arg0)
        {
            if (!condition)
                throw new AssertException(string.Format("arg0:{0}", (object) arg0));
        }

        /// <summary>
        /// Throws an <see cref="T:Quantum.AssertException" /> if condition is false.
        /// Is stripped in release configuration.
        /// </summary>
        /// <param name="condition">Condition</param>
        /// <param name="arg0">Argument is added to the exception message using arg0.ToString()</param>
        /// <param name="arg1">Argument is added to the exception message using arg1.ToString()</param>
        [Conditional("DEBUG")]
        public static void Check<T0, T1>([DoesNotReturnIf(false)] bool condition, T0 arg0, T1 arg1)
        {
            if (!condition)
                throw new AssertException(string.Format("arg0:{0} arg1:{1}", (object) arg0, (object) arg1));
        }

        /// <summary>
        /// Throws an <see cref="T:Quantum.AssertException" /> if condition is false.
        /// Is stripped in release configuration.
        /// </summary>
        /// <param name="condition">Condition</param>
        /// <param name="arg0">Argument is added to the exception message using arg0.ToString()</param>
        /// <param name="arg1">Argument is added to the exception message using arg1.ToString()</param>
        /// <param name="arg2">Argument is added to the exception message using arg2.ToString()</param>
        [Conditional("DEBUG")]
        public static void Check<T0, T1, T2>([DoesNotReturnIf(false)] bool condition, T0 arg0, T1 arg1, T2 arg2)
        {
            if (!condition)
                throw new AssertException(string.Format("arg0:{0} arg1:{1} arg2:{2}", (object) arg0, (object) arg1, (object) arg2));
        }

        /// <summary>
        /// Throws an <see cref="T:Quantum.AssertException" /> if condition is false.
        /// Is stripped in release configuration.
        /// </summary>
        /// <param name="condition">Condition</param>
        /// <param name="arg0">Argument is added to the exception message using arg0.ToString()</param>
        /// <param name="arg1">Argument is added to the exception message using arg1.ToString()</param>
        /// <param name="arg2">Argument is added to the exception message using arg2.ToString()</param>
        /// <param name="arg3">Argument is added to the exception message using arg3.ToString()</param>
        [Conditional("DEBUG")]
        public static void Check<T0, T1, T2, T3>([DoesNotReturnIf(false)] bool condition, T0 arg0, T1 arg1, T2 arg2, T3 arg3)
        {
            if (!condition)
                throw new AssertException(string.Format("arg0:{0} arg1:{1} arg2:{2} arg3:{3}", (object) arg0, (object) arg1, (object) arg2, (object) arg3));
        }

        /// <summary>
        /// Throws an <see cref="T:Quantum.AssertException" /> if condition is false.
        /// Is stripped in release configuration.
        /// </summary>
        /// <param name="condition">Condition</param>
        /// <param name="format">Exception message</param>
        /// <param name="arg0">Argument is added to the exception message using string.Format()</param>
        [Conditional("DEBUG")]
        public static void Check<T0>([DoesNotReturnIf(false)] bool condition, string format, T0 arg0)
        {
            if (!condition)
                throw new AssertException(string.Format(format, (object) arg0));
        }

        /// <summary>
        /// Throws an <see cref="T:Quantum.AssertException" /> if condition is false.
        /// Is stripped in release configuration.
        /// </summary>
        /// <param name="condition">Condition</param>
        /// <param name="format">Exception message</param>
        /// <param name="arg0">Argument is added to the exception message using string.Format()</param>
        /// <param name="arg1">Argument is added to the exception message using string.Format()</param>
        [Conditional("DEBUG")]
        public static void Check<T0, T1>([DoesNotReturnIf(false)] bool condition, string format, T0 arg0, T1 arg1)
        {
            if (!condition)
                throw new AssertException(string.Format(format, (object) arg0, (object) arg1));
        }

        /// <summary>
        /// Throws an <see cref="T:Quantum.AssertException" /> if condition is false.
        /// Is stripped in release configuration.
        /// </summary>
        /// <param name="condition">Condition</param>
        /// <param name="format">Exception message</param>
        /// <param name="arg0">Argument is added to the exception message using string.Format()</param>
        /// <param name="arg1">Argument is added to the exception message using string.Format()</param>
        /// <param name="arg2">Argument is added to the exception message using string.Format()</param>
        [Conditional("DEBUG")]
        public static void Check<T0, T1, T2>(
            [DoesNotReturnIf(false)] bool condition,
            string format,
            T0 arg0,
            T1 arg1,
            T2 arg2)
        {
            if (!condition)
                throw new AssertException(string.Format(format, (object) arg0, (object) arg1, (object) arg2));
        }

        /// <summary>
        /// Throws an <see cref="T:Quantum.AssertException" /> if condition is false.
        /// Is stripped in release configuration.
        /// </summary>
        /// <param name="condition">Condition</param>
        /// <param name="format">Exception message</param>
        /// <param name="args">Argument list added to the message using string.Format()</param>
        [Conditional("DEBUG")]
        public static void Check([DoesNotReturnIf(false)] bool condition, string format, params object[] args)
        {
            if (!condition)
                throw new AssertException(string.Format(format, args));
        }
    }
}